/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.apps.controllers;

/**
 *
 * @author ARIJIT PAL
 */
import com.apps.ui.FileDownloadUI;
import com.jcraft.jsch.*;
import java.io.*;

public class ScpFromController implements Runnable {

    private Channel channel;
    private Session session;

    private double progress;
    
    //UI
    private FileDownloadUI fileDownloadUI;
    //
    String host;
    String port;
    String user;
    String passwd;
    String fileName;
    String saveAsLocal;
    //

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(String port) {
        this.port = port;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public void setSaveAsLocal(String saveAsLocal) {
        this.saveAsLocal = saveAsLocal;
    }
    
    public double getProgress(){
        return progress;
    }
    
    public void setFileDownloadUI(FileDownloadUI fileDownloadUI){
        this.fileDownloadUI = fileDownloadUI;
    }
    
    private void setConig(String host, String port, String user, String passwd){
        progress = 0.0;
        try{
            JSch jsch = new JSch();
            session = jsch.getSession(user, host, Integer.valueOf(port));
            session.setPassword(passwd);
            session.setConfig("StrictHostKeyChecking", "no");
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    @Override
    public void run(){
        getFile(host, port, user, passwd, fileName, saveAsLocal);
    }
    //PUBLIC
    public void getFile(String host, String port, String user, String passwd,
                        String fileName, String saveAsLocal) {

        System.out.println("SCP PARAM: "+fileName+"<>"+saveAsLocal);
        FileOutputStream fos = null;
        try {
            //setting up files local & remote
            String rfile = fileName;
            String lfile = saveAsLocal;
            
            if(fileDownloadUI != null){
                fileDownloadUI.getFileNameText().setText(rfile);
            }
            
            String prefix = null;
            if (new File(lfile).isDirectory()) {
                prefix = lfile + File.separator;
            }

            //Setting up ssh session 
            setConig(host, port, user, passwd);

            //connecting ssh session
            session.connect();

            // exec 'scp -f rfile' remotely
            String command = "scp -f " + rfile;
            channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);

            // get I/O streams for remote scp
            OutputStream out = channel.getOutputStream();
            InputStream in = channel.getInputStream();

            channel.connect();

            byte[] buf = new byte[1024];

            // send '\0'
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();

            while (true) {
                int c = checkAck(in);
                if (c != 'C') {
                    break;
                }

                // read '0644 '
                in.read(buf, 0, 5);

                long filesize = 0L;
                while (true) {
                    if (in.read(buf, 0, 1) < 0) {
                        // error
                        break;
                    }
                    if (buf[0] == ' ') {
                        break;
                    }
                    filesize = filesize * 10L + (long) (buf[0] - '0');
                }
                //System.out.println(filesize);
                String file = null;
                for (int i = 0;; i++) {
                    in.read(buf, i, 1);
                    if (buf[i] == (byte) 0x0a) {
                        file = new String(buf, 0, i);
                        break;
                    }
                }

                //System.out.println("filesize="+filesize+", file="+file);

                // send '\0'
                buf[0] = 0;
                out.write(buf, 0, 1);
                out.flush();

                // read a content of lfile
                fos = new FileOutputStream(prefix == null ? lfile : prefix + file);
                int foo;
                long orSize = filesize;
                while (true) {
                    if (buf.length < filesize) {
                        foo = buf.length;
                    } else {
                        foo = (int) filesize;
                    }
                    //System.out.println(foo + " " + filesize + " " + orSize + " " + buf.length);
                    progress = (double)((double)((double)(orSize - filesize)/orSize)*100.0);
                    if(fileDownloadUI != null){
                        //fileDownloadUI.getFileNameText().setText(rfile);
                        fileDownloadUI.getProgressBar().setValue((int)progress);
                    }
                    //System.out.println(progress);
                    foo = in.read(buf, 0, foo);
                    if (foo < 0) {
                        // error
                        break;
                    }
                    fos.write(buf, 0, foo);
                    filesize -= foo;
                    if (filesize == 0L) {
                        break;
                    }
                }
                fos.close();
                fos = null;

                if (checkAck(in) != 0) {
                    return;//System.exit(0);
                }

                // send '\0'
                buf[0] = 0;
                out.write(buf, 0, 1);
                out.flush();
            }

            session.disconnect();

            return;//return;//System.exit(0);
        } catch (Exception e) {
            System.out.println(e);
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (Exception ee) {
            }
        }
    }

    private int checkAck(InputStream in) throws IOException {
        int b = in.read();
        // b may be 0 for success,
        //          1 for error,
        //          2 for fatal error,
        //          -1
        if (b == 0) {
            return b;
        }
        if (b == -1) {
            return b;
        }

        if (b == 1 || b == 2) {
            StringBuffer sb = new StringBuffer();
            int c;
            do {
                c = in.read();
                sb.append((char) c);
            } while (c != '\n');
            if (b == 1) { // error
                System.out.print(sb.toString());
            }
            if (b == 2) { // fatal error
                System.out.print(sb.toString());
            }
        }
        return b;
    }
    public static void main(String[] args){
        ScpFromController obj = new ScpFromController();
        obj.getFile("192.168.56.102", "22", "arijitpal", "pa00word", "LogEx", "LogEx");
    }
}
